
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;

namespace Swaf.BizObj.Virtual
{
	public class SimpleVirtualBizObjList : BaseBizObjList
	{
		protected static int s_defaultCount = 1000;

		protected string m_getGroupBizRule = null, m_getTotalCountBizrule = null;
		protected int m_pageSize = 20;
		protected int m_currentPage = 0;
		protected int m_lastTotalCount = s_defaultCount;
		protected IBizObjList m_pageData = null;
		protected object[] m_getRuleParams = null;
		protected object[] m_getCountParams;

		public SimpleVirtualBizObjList(string bizObjType, string getGroupBizRule, string getTotalCountBizRule, object[] ruleParams)
			: this(bizObjType, getGroupBizRule, getTotalCountBizRule, 20, ruleParams)
		{
		}

		public SimpleVirtualBizObjList(string bizObjType, string getGroupBizRule, string getTotalCountBizRule, int pageSize, object[] ruleParams)
		{
			base.m_bizObjType = App.bizObjMgr.getDefinition(bizObjType);
			m_getGroupBizRule = getGroupBizRule;
			m_getTotalCountBizrule = getTotalCountBizRule;
			if (m_getTotalCountBizrule != null)
				m_lastTotalCount = -1;
			m_pageSize = pageSize;
			m_getCountParams = ruleParams;
			m_getRuleParams = new object[ruleParams.Length +2];
			ruleParams.CopyTo(m_getRuleParams, 2);
		}

		public override IBizObj this[int index]
		{
			get
			{
				int reqPage = (int)Math.Floor((double)(index / m_pageSize)) +1;
				if (reqPage != m_currentPage)
				{
					m_getRuleParams[0] = m_pageSize;
					m_getRuleParams[1] = reqPage;
					IResults rc = App.ruleMgr.execute(m_getGroupBizRule, m_getRuleParams);
					m_pageData = rc.CallResults as IBizObjList;
					if (m_pageData != null)
					{
						m_currentPage = reqPage;
						if (m_getTotalCountBizrule == null)
						{
							if (m_pageData.numElements < m_pageSize)
								m_lastTotalCount = ((reqPage - 1) * m_pageSize) + m_pageData.numElements;
							else if (m_pageSize * reqPage >= m_lastTotalCount)
								m_lastTotalCount *= 2;
						}
					}
							
				}
				int curPageIndex = index % m_pageSize;
				if (m_pageData != null && curPageIndex < m_pageData.numElements)
					return m_pageData[curPageIndex];

				return null;
			}
			set
			{
			}
		}

		public override void Insert(int index, object value)
		{
			if (numElements == 0)
			{
				m_pageData = App.bizObjMgr.createList(m_bizObjType.Name);
				m_currentPage = 1;

			}
			else if (m_currentPage == 0)//ensure the given page is in place
			{
				IBizObj x = this[(index < numElements) ? index : 0];
			}

			int reqPage = (int)Math.Floor((double)(index / m_pageSize)) +1;
			if (reqPage == m_currentPage)
			{
				m_pageData.Insert(index - ((reqPage-1) * m_pageSize), value);
				m_lastTotalCount++;
			}
		}

		public override int Add(object value)
		{
			this.Insert(numElements, value);
			return numElements;
		}


		public override IBizObj insertNew()
		{
			return App.bizObjMgr.create(m_bizObjType.Name);
		}

		public override int numElements
		{
			get 
			{
				if (m_lastTotalCount == -1 && m_getTotalCountBizrule != null)
				{
					IResults rc = App.ruleMgr.execute(m_getTotalCountBizrule, m_getCountParams);
					if (rc.CallResults is int)
						m_lastTotalCount = (int)rc.CallResults;
				}
				return m_lastTotalCount;

			}
		}

		public override IBizObj insertNewMakeCopy(IBizObj obj)
		{
			throw new Exception("The method or operation is not implemented.");
		}

		public override void refresh()
		{
			throw new Exception("The method or operation is not implemented.");
		}

		public override string getXml(string name, string decoInfo, bool setOnly, bool dirtyOnly, bool newOnly, bool getBasic, bool getObjs, bool getILists, bool getSysVals, System.Xml.XmlTextWriter xmlOut)
		{
			bool madeXmlOut = false;
			StringWriter strBuf = null;
			if (xmlOut == null)
			{
				strBuf = new StringWriter();
				xmlOut = new XmlTextWriter(strBuf);
				xmlOut.Formatting = Formatting.Indented;
				madeXmlOut = true;
			}
			if (name != "")
				xmlOut.WriteStartElement(name);
			if (getSysVals)
				xmlOut.WriteAttributeString("type", this.m_bizObjType.Name);

			if (numElements > 0 || !setOnly)
				for (int pos = 0; pos < numElements; ++pos)
				{
					IBizObj obj = this[pos];
					obj.getXml(null, decoInfo, setOnly, dirtyOnly, newOnly, getBasic, getObjs, getILists, getSysVals, xmlOut);
				}

			if (name != "")
				xmlOut.WriteEndElement();
			if (madeXmlOut)
			{
				xmlOut.Close();
				strBuf.Close();
				return strBuf.ToString();
			}
			return null;
		}

		public override string getXml(string name, bool setOnly, bool dirtyOnly, bool newOnly, bool getBasic, bool getObjs, bool getILists, bool getSysVals, System.Xml.XmlTextWriter xmlOut)
		{
			return getXml(name, BaseBizObj.DefaultFieldDecoInfo, setOnly, dirtyOnly, newOnly, getBasic, getObjs, getILists, getSysVals, xmlOut);
		}

		public override void removeAt(int index)
		{
			throw new Exception("The method or operation is not implemented.");
		}

		public override IBizObjCursor createCursor()
		{
			return new basic.FullBizObjCursor(this);
		}

		public override IBizObj search(string fieldList, object matchValue)
		{
			IBizObj o = null;
			if (m_pageData != null)
				o = m_pageData.search(fieldList, matchValue);
			return o;
		}

		public override IBizObj search(string fieldList, object matchValue, bool findNearestMatch)
		{
			IBizObj o = null;
			if (m_pageData != null)
				o = m_pageData.search(fieldList, matchValue, findNearestMatch);
			return o;
		}

		public override object Clone()
		{
			throw new Exception("The method or operation is not implemented.");
		}

		public override void Clear()
		{
			m_pageData = null;
			m_lastTotalCount = -1;
		}

		protected IApplication App { get { return Application.currentApp; } }
	}
}
